from typing import Annotated
import re
import secrets

from fastapi import Body
from pydantic import BaseModel, model_validator
from app.utils import regexes, types
from app.models.common import AccountId
from app.models import responses


class ModifyPassword(AccountId):
    """修改密码"""
    old_password: str
    new_password: str

    @model_validator(mode='before')
    @classmethod
    def before(cls, data):
        data = types.safe_dict(data)
        data['old_password'] = data.get('old_password', '')
        data['new_password'] = data.get('new_password', '')
        return data

    @model_validator(mode='after')
    def after(self):
        if not re.search(re.compile(regexes.PASSWORD), self.old_password):
            raise responses.FailureResponseError(
                -102, msg='旧密码至少 8 位且必须含大小写字母以及特殊字符(@+#%&_+=)中的一个')

        if not re.search(re.compile(regexes.PASSWORD), self.new_password):
            raise responses.FailureResponseError(
                -102, msg='新密码至少 8 位且必须含大小写字母以及特殊字符(@+#%&_+=)中的一个')

        if secrets.compare_digest(self.old_password, self.new_password):
            raise responses.FailureResponseError(-208)

        return self


ModifyPasswordJSON = Annotated[ModifyPassword, Body()]


class AccountLogin(BaseModel):
    """账号登录"""
    captcha: bool
    username: str
    password: str

    @model_validator(mode='before')
    @classmethod
    def before(cls, data):
        data = types.safe_dict(data)
        data['username'] = data.get('username', '')
        data['password'] = data.get('password', '')
        data['captcha'] = data.get('captcha', False)
        return data

    @model_validator(mode='after')
    def after(self):
        if not self.captcha:
            raise responses.FailureResponseError(-102, msg='请先通过登录验证')

        if not (6 <= len(self.username) <= 32):
            raise responses.FailureResponseError(-102, msg='用户名长度应介于 6-32 位')

        if not re.search(re.compile(regexes.PASSWORD), self.password):
            raise responses.FailureResponseError(
                -102, msg='密码至少 8 位且必须含大小写字母以及特殊字符(@+#%&_+=)中的一个')

        return self


AccountLoginJSON = Annotated[AccountLogin, Body()]
